home *** CD-ROM | disk | FTP | other *** search
/ Our Solar System / Our Solar System.iso / shuttle / seesat3 / readel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-24  |  13.3 KB  |  521 lines

  1. /*
  2. READEL.C
  3. by Paul S. Hirose, 1990 Nov 12
  4. Handles orbital element files and reads the elements.
  5.  
  6. This file is in the public domain.
  7.  
  8. 400 - 499
  9.  
  10. library functions, typedefs, and #defines used in this file:
  11.  
  12. atof atoi cos EOF fclose FILE fopen free fseek ftell getc isdigit
  13. isspace NULL printf strcmp strcpy
  14. */
  15.  
  16. #include "b:seesat.h"    /* global header */
  17.  
  18. extern void free(), printf();
  19. extern char *strcpy();
  20. extern int atoi(), fclose(), getc(), isdigit(), isspace(), strcmp();
  21. extern long int fseek(), ftell();
  22. extern double atof(), cos();
  23. extern FILE *fopen();
  24.  
  25. /* Number of lines on your terminal.  Only affects the listing of satellite
  26. names.  You will get LINES-1 rows of names, followed by "more>" on a separate
  27. line.  The cursor will be positioned to the right of '>'. */
  28. #define LINES 24
  29.  
  30. /* Maximum number of chars to accept from satellite name field in file.  May
  31. be from 1 to 22. */
  32. #define LNAME 22
  33.  
  34. #define BSIZE 50    /* # of index entries in a storage block */
  35.  
  36. #define NSTAT 0        /* normally 0.  Non-zero makes static functions
  37.             and data extern, for testing */
  38.  
  39. #if NSTAT
  40. /* define & declare all functions in this file as extern */
  41. #define STATIC
  42. #define SC extern
  43.  
  44. #else
  45. #define STATIC static
  46. #define SC static
  47. #endif
  48.  
  49. /*############################ LOCAL DATA ############################*/
  50.  
  51. STATIC FILE *fp = NULL;        /* orbital element file */
  52.  
  53. struct node {            /* hash node for index of satellites */
  54.     char name[LNAME+1];    /* satellite name */
  55.     long int offset;    /* location of element set in file */
  56.     struct node *link;    /* point to next struct in chain */
  57. };
  58.  
  59. STATIC struct node *heads[8];        /* hash table */
  60.  
  61. struct bloc {    /* space for BSIZE index entries */
  62.     struct node nodes[BSIZE];
  63.     struct bloc *next;    /* link to next block */
  64. };
  65.  
  66. STATIC struct bloc *first;    /* ptr to first block */
  67.  
  68. STATIC unsigned sets;        /* number of element sets in file */
  69.  
  70. /*######################## LOCAL FUNCTIONS ########################*/
  71.  
  72. SC double angle();    /* convert string to angle in radians */
  73. SC int csum();        /* checksums a line of data */
  74. SC double epjd();    /* converts NORAD Epoch string to epoch */
  75. SC int getel();        /* transfers elements from file to variables */
  76. SC int getlin();    /* move a line from file to buffer */
  77. SC unsigned hash();    /* turns string into value from 0 to 7 */
  78. SC void nullsp();    /* replace spaces in buffer with nulls */
  79. SC double sci();    /* returns value of scientific notation #'s */
  80. SC char *sknull();    /* skip leading nulls */
  81.  
  82. /*############################## CODE ##############################*/
  83.  
  84. STATIC double
  85. angle(string)
  86. char *string;
  87. /* Returns the radian value of the angle (degrees) in "string".
  88. Leading nulls on "string" will be skipped, so it had better contain
  89. at least one digit. */
  90. {
  91.     return atof(sknull(string)) * de2ra;
  92. }
  93.  
  94.  
  95. STATIC int
  96. csum(line)
  97. char *line;
  98. /* Does a checksum modulo 10 on the given line.  Digits = their
  99. value, '-' = 1, '+' = 2, all other chars = 0.  Returns 0 if ok. */
  100. {
  101.     char c;
  102.     int i = 0;    /* checksum accumulator */
  103.     int count = 69;        /* length of data line */
  104.  
  105.     /* accumulate checksum from all but the last char in the line,
  106.     which is the desired checksum */
  107.  
  108.     while (--count) {
  109.         if (isdigit(c = *line++))
  110.             i += c - '0';
  111.         else if (c == '-')
  112.             ++i;
  113.         else if (c == '+')
  114.             i += 2;
  115.         /* all other chars = 0 */
  116.     }
  117.  
  118.     /* Convert accumulated # to mod 10, subtract desired sum */
  119.     return i % 10 - (*line - '0');
  120. }
  121.  
  122.  
  123. STATIC double
  124. epjd(buf)
  125. char *buf;
  126. /* Given pointer to the orbital elements Epoch field, returns Julian Date
  127. (unit = minutes).  Positions for Days tens and hundreds and Years tens digits
  128. must contain either a digit or '\0'.  Format of Epoch field:  YYDDD.dddddddd
  129. */
  130. {    
  131.     double day;
  132.     int year;
  133.  
  134.     day = atof(sknull(buf + 2));
  135.  
  136.     buf[2] = '\0';            /* day 100s digit = null */
  137.     year = atoi(sknull(buf));
  138.     year += (year < 57) ? 1999 : 1899;
  139.  
  140.     /* Subtract .5 because julday() returns JD at 12h on given day */
  141.     return (julday(year, 11, 31) + day - .5) * xmnpda;
  142. }
  143.  
  144.  
  145. STATIC int
  146. getel()
  147. /* Sets the global orbital element variables and name[] (satellite name)
  148. using data from the currently open element file.  Initializes precession. 
  149. Sets global iflag to 1.  The position in the file must be at the satellite
  150. name or in white space preceding the name.  Returns -1 if incorrect format in
  151. file, 0 if near-earth object, 1 if deep space.  Prints warning if checksum
  152. error in file, but will still attempt to use elements. */
  153. {
  154.     double ao, a1, delo, del1, temp;
  155.     int check;
  156.     char line1[70], line2[70];
  157.  
  158.     getlin(name, LNAME+1);
  159.  
  160.     /* Get first data line from file.  Verify that it's 69 chars long &
  161.     begins with '1' */
  162.  
  163.     if (getlin(line1, 70) != 69 || *line1 != '1')
  164.         return -1;    /* incorrect format */
  165.     check = csum(line1);    /* Line 1 checksum */
  166.  
  167.     /* get second data line */
  168.     if (getlin(line2, 70) != 69 || *line2 != '2')
  169.         return -1;    /* incorrect format */
  170.     check += csum(line2);    /* add Line 2 checksum */
  171.  
  172.     /* print both lines at console */
  173.     printf("%s\n%s\n", line1, line2);
  174.     if (check)
  175.         printf("CAUTION:  FAILED CHECKSUM\n");
  176.  
  177.     /* replace spaces with nulls */
  178.     nullsp(line1);
  179.     nullsp(line2);
  180.  
  181.     xmo = angle(line2 + 43);
  182.     xnodeo = angle(line2 + 17);
  183.     omegao = angle(line2 + 34);
  184.     xincl = angle(line2 + 8);
  185.     FTEST((400, 4, 3, &xmo, &xnodeo, &omegao, &xincl));
  186.  
  187.     /* put a decimal point in front of eccentricity, decode it */
  188.     line2[25] = '.';
  189.     eo = atof(line2 + 25);
  190.  
  191.     temp = twopi / (xmnpda * xmnpda);
  192.  
  193.     /* Make sure mean motion is null-terminated, since rev. no.
  194.     may immediately follow. */
  195.     line2[63] = '\0';
  196.     xno = atof(sknull(line2 + 52)) * temp * xmnpda;
  197.     if (line1[35])        /* field isn't blank */
  198.         xndt2o = atof(sknull(line1 + 33)) * temp;
  199.     else
  200.         xndt2o = 0.;
  201.     xndd6o = sci(line1 + 44) * temp / xmnpda;
  202.  
  203.     bstar = sci(line1 + 53);
  204.     epoch = epjd(line1 + 18);
  205.     ETEST((402, 5, 3, &eo, &xno, &xndt2o, &xndd6o, &bstar));
  206.     FTEST((403, 1, 3, &epoch));
  207.  
  208.     toffs = 0.;    /* reset OFFSET */
  209.     iflag = 1;
  210.  
  211. #if ENPRE    /* precession code enabled */
  212.     /* initialize direction cosines to precess R.A./dec. */
  213.     inpre();
  214. #endif
  215.  
  216.     /* Compute period.  Object is deep space if <= 6.4 revs/day */
  217.     a1 = POW(xke / xno, tothrd);
  218.     temp = cos(xincl);
  219.     temp = 1.5 * ck2 * (3. * temp * temp - 1.) /
  220.       POW(1. - eo * eo, 1.5);
  221.     del1 = temp / (a1 * a1);
  222.     ao = a1 * (1. - del1 * (.5 * tothrd + del1 *
  223.       (1. + 134. / 81. * del1)));
  224.     delo = temp / (ao * ao);
  225.  
  226.     if (xno / (1. + delo) <= .0279253)
  227.         return 1;    /* deep space */
  228.     else
  229.         return 0;    /* near earth */
  230. }
  231.  
  232.  
  233. STATIC int
  234. getlin(dest, size)
  235. int size;    /* must be at least 2 */
  236. char *dest;
  237. /* Copy a line from the currently open file into dest[].  "Size" is length of
  238. dest[], and must be at least 2.  Any leading white space is skipped.  String
  239. copied to dest[] will be null terminated.
  240.      Exit occurs when:  1) size - 1 chars have been copied, or 2) '\n'
  241. detected (the '\n' won't be sent to dest[]), or 3) EOF detected.  In case 1
  242. or 2, the next read from the file is guaranteed to start at beginning of the
  243. next line.  Returns # of chars copied to dest[] (final null not counted). */
  244. {
  245.     int c, i;
  246.  
  247.     i = size - 1;    /* i = # of chars desired */
  248.  
  249.     /* go past leading white space */
  250.     while (isspace(c = getc(fp)))
  251.         ;
  252.  
  253.     /* Move chars to buffer till we we reach end of line, or
  254.     have gotten # requested, or end of file. */
  255.  
  256.     do {
  257.         if (c == EOF)
  258.             break;
  259.         *dest++ = c;
  260.     } while (--i && (c = getc(fp)) != '\n');
  261.     *dest = '\0';
  262.  
  263.     /* At this point, i is how many chars we've fallen short */
  264.  
  265.     if (!i)        /* requested # of chars were found */
  266.         while ((c = getc(fp)) != '\n' && c != EOF)
  267.             ;    /* position at start of next line */
  268.  
  269.     return size - 1 - i;    /* how many copied */
  270. }
  271.  
  272.  
  273. STATIC unsigned
  274. hash(string)
  275. char *string;
  276. /* Add all chars in string, returns sum modulo 8 */
  277. {
  278.     unsigned sum;
  279.     char c;
  280.  
  281.     for (sum = 0; c = *string++; )
  282.         sum += c;
  283.     return sum & 7;
  284. }
  285.  
  286.  
  287. void
  288. hfree()        /* frees the index space */
  289. {
  290.     struct bloc *blocp;
  291.  
  292.     for (blocp = first;  blocp;  blocp = blocp->next)
  293.         free((VOIDP) blocp);
  294.     first = NULL;
  295. }
  296.  
  297.  
  298. void
  299. index()
  300. /* List all satellites in the index generated by opn(). */
  301. {
  302.     unsigned total, u, line, column;
  303.     struct bloc *blocp;
  304.     struct node *nodep;
  305.  
  306.     ++tokp;        /* point to next command */
  307.  
  308.     total = sets;    /* total no. of element sets in file */
  309.     line = LINES - 1;
  310.     column = 3;
  311.  
  312.     for (blocp = first;  blocp;  blocp = blocp->next) {
  313.         nodep = blocp->nodes;
  314.         for (u = BSIZE;    u--; ) {
  315.             if (line == 0) {    /* screen is full */
  316.                 printf("more");
  317.                 tok();        /* cmd line prompt */
  318.                 if (*tokp)    /* cmd was typed */
  319.                     return;
  320.                 else        /* only a CR was typed */
  321.                     line = LINES - 1;
  322.             }
  323.             if (--column)
  324.                 printf("%-25s", nodep->name);
  325.             else {        /* rightmost column */
  326.                 printf("%s\n", nodep->name);
  327.                 column = 3;
  328.                 --line;
  329.             }
  330.             ++nodep;
  331.             if (--total == 0)
  332.                 break;
  333.     }    }
  334.     if (column != 3)
  335.         printf("\n");
  336. }
  337.  
  338.  
  339. void
  340. load()
  341. /* Takes the next argument on the command line as the name of the satellite
  342. to load from the currently open file. */
  343. {
  344.     struct node *nodep;
  345.  
  346.     ++tokp;        /* point to name */
  347.  
  348.     /* search hash table for a matching name */
  349.     for (nodep = heads[hash(*tokp)]; nodep; nodep = nodep->link)
  350.         if (strcmp(nodep->name, *tokp) == 0)
  351.             break;    /* found matching name */
  352.  
  353.     if (nodep) {
  354.     /* found matching name */
  355.         fseek(fp, nodep->offset, 0);
  356.  
  357.         /* get elements, report status */
  358.         switch (getel()) {
  359.         case -1:
  360.             printf("ABORTED LOAD:  INCORRECT FORMAT\n");
  361.             break;
  362.         case 0:
  363.             printf("satellite loaded\n");
  364.             break;
  365.         case 1:
  366.             printf("CAUTION:  DEEP SPACE SATELLITE\n");
  367.         }
  368.     } else
  369.         printf("NO SUCH SATELLITE\n");
  370.     ++tokp;        /* point to next command */
  371. }
  372.  
  373.  
  374. STATIC void
  375. nullsp(buf)
  376. char *buf;
  377. /* replaces each occurrence of ' ' in string "buf" with a null */
  378. {
  379.     char c;
  380.  
  381.     while (c = *buf) {
  382.         if (c == ' ')
  383.             *buf = '\0';
  384.         ++buf;
  385. }    }
  386.  
  387.  
  388. void
  389. opn()
  390. /* Take the next argument on the command line as the name of the orbital
  391. element file to open.  Builds the index used by index() and load().  If an
  392. elements file is already open, it will be closed and the associated index
  393. deleted before opening the new file.  External "fp" is set to the returned
  394. value from fopen(). */
  395. {
  396.     struct bloc *blocp, *last;
  397.  
  398.     FILE *tfp;
  399.     long int fpos;        /* position in file */
  400.     unsigned int n50, hshval;
  401.     char *cp, buffer[70];
  402.     struct node *indexp, *nodep;
  403.  
  404.     tokp += 2;    /* point to next command */
  405.  
  406.     if ((tfp = fopen(*(tokp - 1), "r")) == NULL) {
  407.         printf("CAN'T OPEN %s\n", *(tokp - 1));
  408.         return;
  409.     }
  410.  
  411.     if (fp) {    /* close old file, delete its index */
  412.         struct node **nodepp;
  413.         unsigned u;
  414.  
  415.         fclose(fp);
  416.         hfree();        /* release index space */
  417.         nodepp = heads;
  418.         for (u = 8; u--; )
  419.             *nodepp++ = NULL;    /* clear hash table */
  420.     }
  421.  
  422.     fp = tfp;
  423.     sets = 0;    /* counts # of element sets processed */
  424.     n50 = 0;    /* storage remaining */
  425.     fpos = 0L;    /* position in file */
  426.  
  427.     while (getlin(buffer, LNAME+1) != 0) {
  428.     /* got a satellite name; add it to index */
  429.         if (n50 == 0) {    /* need more storage */
  430.             blocp = MALLOC(sizeof (struct bloc));
  431.             if (blocp) {
  432.                 if (first == NULL)    /* first block */
  433.                     first = blocp;
  434.                 else
  435.                     last->next = blocp;
  436.                 last = blocp;
  437.                 blocp->next = NULL;    /* end of chain */
  438.                 indexp = blocp->nodes;
  439.                 n50 = BSIZE;    /* reset storage counter */
  440.             } else {
  441.                 printf("MEMORY FULL:  %u INDEXED\n", sets);
  442.                 return;
  443.         }    }
  444.         /* add the element set to the index */
  445.  
  446.         /* eliminate any trailing spaces on name */
  447.         for (cp = buffer; *++cp; )
  448.             ;    /* find end of name string */
  449.         while (isspace(*--cp))
  450.             ;    /* point to last non-white char */
  451.         cp[1] = '\0';
  452.  
  453.         strcpy(indexp->name, stoup(buffer));
  454.         indexp->offset = fpos;        /* location in file */
  455.         indexp->link = NULL;        /* end of chain mark */
  456.  
  457.         /* link it to the hash table */
  458.         hshval = hash(buffer);        /* hash satellite name */
  459.         if (nodep = heads[hshval]) {
  460.         /* hash table entry is already taken */
  461.             while (nodep->link)
  462.                 nodep = nodep->link;    /* find end of chain */
  463.             nodep->link = indexp;    /* attach new entry */
  464.         } else
  465.             heads[hshval] = indexp;
  466.  
  467.         getlin(buffer, 70);    /* move past Line 1 */
  468.         getlin(buffer, 70);    /* move past Line 2 */
  469.         ++sets;            /* # of satellites found */
  470.         --n50;        /* space remaining in index */
  471.         ++indexp;    /* point to next free place in index */
  472.         fpos = ftell(fp);    /* update file position */
  473.     }
  474.     printf("complete; %u satellites found\n", sets);
  475. }
  476.  
  477.  
  478. STATIC double
  479. sci(string)
  480. char *string;
  481. /* Converts quasi scientific notation to double.  Format:  SnSn where S is
  482. either '-' or '\0' and n represents a sequence of 1 or more digits.  An
  483. implied decimal point exists to the left of the left n.  Total length 27
  484. chars max. */
  485. {
  486.     char buf[30], *bufptr;
  487.  
  488.     bufptr = buf;
  489.  
  490.     if (string[1] == '\0')
  491.         return 0.;
  492.  
  493.     /* get significand */
  494.     if (*string == '-')
  495.         *bufptr++ = '-';
  496.     *bufptr = '.';
  497.     while (isdigit(*++bufptr = *++string))
  498.         ;    /* copy significand */
  499.     *bufptr++ = 'E';
  500.  
  501.     /* get exponent */
  502.     if (*string == '\0')    /* no sign on exponent */
  503.         ++string;
  504.  
  505.     strcpy(bufptr, string);        /* copy exponent */
  506.     return atof(buf);
  507. }
  508.  
  509.  
  510. STATIC char *
  511. sknull(cptr)
  512. char *cptr;
  513. /* Skip nulls.  Returns pointer to first non-null char in "cptr". */
  514. {
  515.     while (!*cptr)
  516.         ++cptr;
  517.  
  518.     return cptr;
  519. }
  520. ndexp;    /* point to next free place in index */
  521.